/**
 * Define la clase App que se encarga de crear la ventana, inicializar la
 * aplicación y manejar el bucle del juego cargando el resto del contenido
 *
 * @file app.h
 * @author Adrián Guerra Marrero
 * @date 20110419
 */

#ifndef APP_H
#define APP_H

#include <string>
#include <fstream>
#include <SFML/Graphics.hpp>
#include "SGE_types.h"

namespace SGE
{

class App
{
public:
	// Constants
	///////////////////////////////////////////////////////////////////////////
	/// Ancho por defecto si no se encuentra archivo de configuración
	static const unsigned int DEFAULT_VIDEO_WIDTH = 640;
	/// Alto por defecto si no se encuentra archivo de configuración
	static const unsigned int DEFAULT_VIDEO_HEIGHT = 480;
	/// bits per pixel (color depth) por defecto
	static const unsigned int DEFAULT_VIDEO_BPP = 32;

	/// Variables
	///////////////////////////////////////////////////////////////////////////
	/// Titulo de la ventana
	std::string mTitle;
	/// Video Mode a usar (width, height, bpp)
	sf::VideoMode mVideoMode;
	/// Ventana de la aplicación
	sf::RenderWindow mWindow;
	/// Opciones de la ventana
	sf::WindowSettings mWindowSettings;
	/// Estilo de la ventana
	unsigned long mWindowStyle;
	/// Input manager para la ventana
	const sf::Input& mInput;
	/// Archivo de log
	std::ofstream mLog;

	/**
	 * App constructor
	 * @param[in] theTitle es el título de la ventana
	 */
	App(const std::string theTitle = "Isometric RTS");

	/**
	 * App Destructor
	 */
	~App();

	/**
	 * ProcessArguments se encarga de procesar los argumentos pasados por
	 * línea de comandos.
	 * @param argc es el numero de argumentos
	 * @param argv es la lista de argumentos
	 */
	virtual void ProcessArguments(int argc, char* argv[]);

	/**
	 * Run es llamado cuando se crea App, se encarga de llamar a los métodos
	 * Init, Loop, y Cleanup.
	 * class.
	 * @return El valor mExitCode que indica el código de salida
	 */
	int Run(void);

	/**
	 * IsRunning will return true if the Application is still running.
	 * @return true if Application is running, false otherwise
	 */
	bool IsRunning(void) const;

	/**
	 * GetUpdateRate will return the current game loop update rate being
	 * used.
	 * @return update rate in Hz (updates per second)
	 */
	float GetUpdateRate(void) const;

	/**
	 * SetUpdateRate will set the game loop update rate to theRate specified
	 * from 1 Hz to 1000 Hz.  Any other value outside this range will not be
	 * accepted.
	 *
	 * @param[in] theRate in Hz (updates per second) range is [1,1000]
	 */
	void SetUpdateRate(float theRate);

	/**
	 * Quit will signal the Application to stop running.
	 * @param[in] theExitCode to use when the Run method returns
	 */
	void Quit(int theExitCode);

protected:
	/**
	 * PreInit is responsible for getting things ready before the derived
	 * classes Init method is called.  This prevents problems that might occur
	 * with how the derived classes Init methods are written.
	 */
	void PreInit(void);

	/**
	 * Init is responsible for initializing the Application.
	 */
	virtual void Init(void);

	/**
	 * Loop is responsible for monitoring IsRunning and exiting when the
	 * Application is done.
	 */
	virtual void Loop(void);

	/**
	 * Cleanup is responsible for performing any last minute Application
	 * cleanup steps before exiting the Application.
	 */
	virtual void Cleanup(void);

private:
	/// The exit code value that will be returned by the program
	int mExitCode;
	/// True if the Application is currently running
	bool mRunning;
	/// Update rate in seconds (1.0f / UpdateRate) to use for game loop
	float mUpdateRate;
	/// Logger output path and filename
	std::string mLogFile;

	App(const App& rhs);
	App& operator=(const App& rhs);

};

} // Namespace SGE

#endif // APP_H
